package com.kmxd.ams.app.system;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kmxd.ams.client.system.ISysFondsSvc;
import com.kmxd.ams.client.system.dto.SysFondsAddDTO;
import com.kmxd.ams.client.system.dto.SysFondsEditDTO;
import com.kmxd.ams.client.system.dto.SysFondsQueryDTO;
import com.kmxd.ams.client.system.vo.SysFondsListVO;
import com.kmxd.ams.client.system.vo.SysFondsVO;
import com.kmxd.ams.core.common.constant.CacheConst;
import com.kmxd.ams.core.common.constant.ErrorCode;
import com.kmxd.ams.core.common.enums.DbTypeEnum;
import com.kmxd.ams.core.common.query.QueryGen;
import com.kmxd.ams.core.config.AmsConfig;
import com.kmxd.ams.core.exception.BizTipException;
import com.kmxd.ams.core.util.IdUtil;
import com.kmxd.ams.core.util.SecurityUtil;
import com.kmxd.ams.infra.system.entity.SysFonds;
import com.kmxd.ams.infra.system.mapper.SysFondsMapper;
import com.kmxd.ams.infra.tmpl.enums.TmplEnum;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 全宗 服务实现类
 *
 * @author ZuoLG
 * @since 2022-07-14
 */
@Service
@Slf4j
@AllArgsConstructor
@CacheConfig(cacheNames = CacheConst.CACHE_PREFIX_SYS_FONDS)
public class SysFondsSvcImpl extends ServiceImpl<SysFondsMapper, SysFonds> implements ISysFondsSvc {

  private final SysFondsMapper sysFondsMapper;
  private final AmsConfig amsConfig;

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public Page<SysFondsListVO> selectPage(Page reqPage, SysFondsQueryDTO req) {
    req.setComId(ObjectUtil.isNotNull(req.getComId()) ? req.getComId() : SecurityUtil.getCropId());
    LambdaQueryWrapper<SysFonds> queryWrapper =
        QueryGen.init(new QueryWrapper<SysFonds>(), req).lambda();
    Page<SysFonds> page = sysFondsMapper.selectPage(reqPage, queryWrapper);
    Page<SysFondsListVO> voPage = BeanUtil.copyProperties(page, Page.class);
    voPage.setRecords(BeanUtil.copyToList(page.getRecords(), SysFondsListVO.class));
    return voPage;
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public List<SysFondsListVO> list(SysFondsQueryDTO req) {
    req.setComId(ObjectUtil.isNotNull(req.getComId()) ? req.getComId() : SecurityUtil.getCropId());
    LambdaQueryWrapper<SysFonds> queryWrapper =
        QueryGen.init(new QueryWrapper<SysFonds>(), req).lambda();
    List<SysFonds> list = sysFondsMapper.selectList(queryWrapper);
    return BeanUtil.copyToList(list, SysFondsListVO.class);
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public List<SysFondsListVO> listAll() {
    LambdaQueryWrapper<SysFonds> queryWrapper = Wrappers.lambdaQuery();
    List<SysFonds> list = sysFondsMapper.selectList(queryWrapper);
    return BeanUtil.copyToList(list, SysFondsListVO.class);
  }

  @CacheEvict(allEntries = true)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void add(SysFondsAddDTO req) {
    SysFonds entity = BeanUtil.copyProperties(req, SysFonds.class);
    entity.setCode(entity.getCode().trim());
    entity.setName(entity.getName().trim());
    entity.setId(IdWorker.getId());
    entity.setComId(
        ObjectUtil.isNotEmpty(req.getComId()) ? req.getComId() : SecurityUtil.getCropId());
    entity.setAutoIndex(getAutoIndex() + 1);
    entity.setSort(entity.getAutoIndex());
    // 设置默认全宗
    entity.setType(getDefFonds(entity.getComId()).size() > 0 ? 0L : 1L);
    if (!this.checkUniqueName(req.getName(), req.getId())) {
      throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "全宗名称已经已存在");
    }
    if (!this.checkUniqueCode(req.getCode(), req.getId())) {
      throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "全宗编码已经已存在");
    }
    sysFondsMapper.insert(entity);
  }

  @Override
  public void checkFonds(SysFondsAddDTO req) {
    SysFonds entity = BeanUtil.copyProperties(req, SysFonds.class);
    entity.setAutoIndex(getAutoIndex() + 1);
    if (!this.checkUniqueName(req.getName(), req.getId())) {
      throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "全宗名称已经已存在");
    }
    if (!this.checkUniqueCode(req.getCode(), req.getId())) {
      throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "全宗编码已经已存在");
    }
    // 判断电子文件是否存在
    String tableName = TmplEnum.efile.getCode() + "_" + entity.getAutoIndex();
    String tableSchema;
    int count = 0;
    if (StrUtil.isBlank(amsConfig.getDbType())
        || StrUtil.equals(DbTypeEnum.MYSQL.getCode(), amsConfig.getDbType())) {
      tableSchema = sysFondsMapper.getDataBaseId();
      count = sysFondsMapper.haveEfileTable(tableSchema, tableName);
    } else {
      tableSchema = amsConfig.getDbName();
      count = sysFondsMapper.haveEfileTablePG(tableSchema, tableName);
    }
    if (count != 0) {
      throw BizTipException.instance(
          ErrorCode.VALIDATE_ERROR, StrUtil.format("电子文件表:[{}]已经存在，请手动处理!", tableName));
    }
  }

  /**
   * 获取自增序号
   *
   * @return
   */
  @Override
  public int getAutoIndex() {
    Integer autoIndex = sysFondsMapper.getAutoIndex();
    return ObjectUtil.isNotEmpty(autoIndex) ? (autoIndex) : 0;
  }

  @Override
  public List<SysFondsListVO> list(long comId) {
    LambdaQueryWrapper<SysFonds> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.eq(ObjectUtil.isNotEmpty(comId), SysFonds::getComId, comId);
    queryWrapper.orderByAsc(SysFonds::getSort);
    List<SysFonds> list = sysFondsMapper.selectList(queryWrapper);
    return BeanUtil.copyToList(list, SysFondsListVO.class);
  }

  @Override
  public List<SysFonds> getDefFonds(long cropId) {
    LambdaQueryWrapper<SysFonds> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.eq(SysFonds::getComId, cropId);
    queryWrapper.eq(SysFonds::getType, 1L);
    List<SysFonds> list = this.sysFondsMapper.selectList(queryWrapper);
    return list;
  }

  @CacheEvict(allEntries = true)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void edit(SysFondsEditDTO req) {
    SysFonds entity = BeanUtil.copyProperties(req, SysFonds.class);
    entity.setCode(entity.getCode().trim());
    entity.setName(entity.getName().trim());
    entity.setComId(
        ObjectUtil.isNotEmpty(req.getComId()) ? req.getComId() : SecurityUtil.getCropId());
    if (!this.checkUniqueName(req.getName(), req.getId())) {
      throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "全宗名称已经已存在");
    }
    if (!this.checkUniqueCode(req.getCode(), req.getId())) {
      throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "全宗编码已经已存在");
    }
    sysFondsMapper.updateById(entity);
  }

  @CacheEvict(allEntries = true)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void remove(String ids) {
    Set<Long> idList = IdUtil.split(ids);
    sysFondsMapper.deleteBatchIds(idList);
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public SysFondsVO view(Long id) {
    SysFonds entity = sysFondsMapper.selectById(id);
    return BeanUtil.copyProperties(entity, SysFondsVO.class);
  }

  private Boolean checkUniqueName(String value, Long id) {
    if (StrUtil.isBlank(value)) {
      return true;
    }
    id = Objects.isNull(id) ? -1L : id;
    SysFonds entity =
        sysFondsMapper.selectOne(Wrappers.lambdaQuery(SysFonds.class).eq(SysFonds::getName, value));
    return Objects.isNull(entity) || NumberUtil.equals(entity.getId(), id);
  }

  private Boolean checkUniqueCode(String value, Long id) {
    if (StrUtil.isBlank(value)) {
      return true;
    }
    id = Objects.isNull(id) ? -1L : id;
    SysFonds entity =
        sysFondsMapper.selectOne(
            Wrappers.lambdaQuery(SysFonds.class).eq(SysFonds::getCode, value.toLowerCase()));
    return Objects.isNull(entity) || NumberUtil.equals(entity.getId(), id);
  }

  @CacheEvict(allEntries = true)
  @Override
  public void clearAllCache() {
    log.info("清除系统缓存");
  }
}
